package com.slipper.system.organization.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.slipper.constants.Constants;
import com.slipper.exception.CommonException;
import com.slipper.core.transaction.ReadTransactional;
import com.slipper.core.transaction.WriteTransactional;
import com.slipper.system.organization.bo.OrganizationBO;
import com.slipper.system.organization.dao.OrganizationDao;
import com.slipper.util.Tool;
import com.slipper.util.UUID;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
@ReadTransactional
public class OrganizationService {
    @Resource
    private OrganizationDao organizationDao;
    
    public OrganizationBO queryBy(String id){
        if (Tool.isBlank(id)) return null;
        return organizationDao.queryBy(id);
    }

    public List<OrganizationBO> queryList(OrganizationBO bo) {
        return organizationDao.queryList(bo);
    }
    
    public PageInfo<OrganizationBO> queryPage(OrganizationBO bo){
        PageHelper.startPage(bo.getPageNumber(), bo.getPageSize());
        return new PageInfo<>(organizationDao.queryList(bo));
    }
    
    @WriteTransactional
    public Integer save(OrganizationBO bo){
        int result;
        if (bo.getParentId() == null) {
            bo.setParentId(Constants.ROOT_ID);
        }

        if (Tool.isNotBlank(bo.getId())) {
            setUnitId(bo);
            bo.setUpdateTime(System.currentTimeMillis());
            result = organizationDao.update(bo);
        } else {
            bo.setId(UUID.getUUID());
            setUnitId(bo);
            bo.setUpdateTime(System.currentTimeMillis());
            bo.setCreateTime(System.currentTimeMillis());
            result = organizationDao.insert(bo);
        }
        
        return result;
    }

    private void setUnitId(OrganizationBO bo) {
        if (OrganizationBO.TYPE_UNIT.equals(bo.getType()) || OrganizationBO.TYPE_ENT.equals(bo.getType())) {
            bo.setUnitId(bo.getId());
        } else if (OrganizationBO.TYPE_DEPT.equals(bo.getType()) && bo.getParentId() != null) {
            OrganizationBO parent = queryBy(bo.getParentId());
            bo.setUnitId(parent == null ? null : parent.getUnitId());
        } else {
            bo.setUnitId(null);
        }
    }
    
    @WriteTransactional
    public Integer delete(OrganizationBO bo){
        return organizationDao.delete(bo);
    }

    public OrganizationBO queryByName(OrganizationBO bo) {
        return organizationDao.queryByName(bo);
    }

    @WriteTransactional
    public void saves(List<OrganizationBO> list) {
        StringBuilder builder = new StringBuilder();
        list.sort(Comparator.comparing(OrganizationBO::getName));
        for (OrganizationBO bo : list) {
            String result = this.saveItem(bo);
            if (result != null && !result.isEmpty()) {
                builder.append(result).append("@@@");
            }
        }
        if (!builder.isEmpty()) throw new CommonException(builder.toString());
    }
    
    @WriteTransactional
    public String saveItem(OrganizationBO bo) {
        String[] levelNames = bo.getName().split("/");
        if (levelNames.length == 0) {
            return null;
        }
        String parentLevelName = "";
        for (int i=0;i<levelNames.length - 1;i++) {
            if (i > 0) {
                parentLevelName = parentLevelName.concat("/");
            }
            parentLevelName = parentLevelName.concat(levelNames[i]);
        }

        bo.setName(levelNames[levelNames.length-1]);
        this.save(bo);
        return null;
    }

    @WriteTransactional
    public int updateValid(OrganizationBO bo) {
        return organizationDao.updateValid(bo);
    }

    public Map<String, Object> queryMapData(String id) {
        return organizationDao.queryMapData(id);
    }

    public List<OrganizationBO> queryRelation(String id) {
        if (Tool.isBlank(id)) return Collections.emptyList();

        OrganizationBO organ = queryUnit(id);
        if (organ == null) return Collections.emptyList();

        List<OrganizationBO> dataList = new ArrayList<>();
        queryChildren(new String[] { organ.getId() }, dataList);
        dataList.add(organ);
        return dataList;
    }

    public OrganizationBO queryUnit(String id) {
        if (Tool.isBlank(id)) return null;

        OrganizationBO organ = organizationDao.queryBy(id);
        if (organ == null) return null;

        if (OrganizationBO.TYPE_AREA.equals(organ.getType())
                || OrganizationBO.TYPE_UNIT.equals(organ.getType())
                || OrganizationBO.TYPE_ENT.equals(organ.getType())
                || Tool.isBlank(organ.getParentId())) {
            return organ;
        }
        return queryUnit(organ.getParentId());
    }

    private void queryChildren(String[] parentIds, List<OrganizationBO> organList) {
        if (parentIds == null || parentIds.length == 0) return;

        List<OrganizationBO> dataList = organizationDao.queryChildren(parentIds);
        if (dataList.isEmpty()) return;

        organList.addAll(dataList);
        queryChildren(dataList.stream().map(OrganizationBO::getId).toList().toArray(new String[0]), organList);
    }
}
